﻿using GKQC.Common;
using GKQC.DbHelper.Dao;
using GKQC.DbHelper.DbModels;
using GKQC.DbHelper.ErpViewModels;
using GKQC.DbHelper.ViewModels;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace GKQC.DbHelper.Services
{
    public class OrtService
    {
        AllDbContext dbContext;
        string trueString = "1";
        string falseString = "2";
        public static string FqcApiData { get; set; }
        public OrtService(AllDbContext dbContext)
        {
            this.dbContext = dbContext;
        }
        public List<OrtHeadModel> GetHeads(int count)
        {
            return dbContext.QcDb.Queryable<OrtHeadModel>().OrderBy(t=>t.TestDate, OrderByType.Desc).Take(count).ToList();
        }

        /// <summary>
        /// 根据料号和客户料号获取最近的一条记录
        /// </summary>
        /// <param name="pn"></param>
        /// <param name="customerPn"></param>
        /// <returns></returns>
        public OrtHeadModel GetHead(string pn, string customerPn)
        {
            return dbContext.QcDb.Queryable<OrtHeadModel>()
                .Where(t=>t.Pn == pn && t.CustomerPn == customerPn)
                .OrderBy(t => t.TestDate, OrderByType.Desc)
                .ToList().FirstOrDefault();
        }

        public bool GetLastCapRateBySeries(string series, out double capmax, out double capmin)
        {
            capmax = capmin = 0;
            bool flag = false;
            if (string.IsNullOrWhiteSpace(series)) return false;
            var v =  dbContext.QcDb.Queryable<OrtHeadModel>()
                .Where(t => t.Series == series)
                .OrderBy(t => t.TestDate, OrderByType.Desc)
                .Select(t=>new { CapMax = t.CapMax, CapMin = t.CapMin})
                .ToList().FirstOrDefault();

            if(v != null)
            {
                capmax = v.CapMax;
                capmin = v.CapMin;
                flag = true;
            }

            return flag;
        }

        /// <summary>
        /// 根据料号和客户料号获取最近的一条记录
        /// </summary>
        /// <param name="pn"></param>
        /// <param name="customerPn"></param>
        /// <param name="billtype">单据类型</param>
        /// <param name="reportId">报表ID</param>
        /// <returns></returns>
        public OrtHeadModel GetHead(string pn, string customerPn,string billtype, int reportId)
        {
            OrtHeadModel ortHeadModel = dbContext.QcDb.Queryable<OrtHeadModel>()
                .Where(t => t.BillType == billtype && t.Pn == pn && t.CustomerPn == customerPn)
                .WhereIF(reportId>0 ,t=>t.ReportId == reportId)
                .OrderBy(t => t.TestDate, OrderByType.Desc)
                .ToList().FirstOrDefault();
            if(ortHeadModel == null && reportId>0)
                ortHeadModel = dbContext.QcDb.Queryable<OrtHeadModel>()
                .Where(t => t.BillType == billtype && t.Pn == pn && t.CustomerPn == customerPn)
                .OrderBy(t => t.TestDate, OrderByType.Desc)
                .ToList().FirstOrDefault();

            return ortHeadModel;
        }

        public OrtHeadModel GetHead(string billtype, int reportId)
        {
            return dbContext.QcDb.Queryable<OrtHeadModel>()
                .Where(t => t.BillType == billtype)
                .WhereIF(reportId > 0, t => t.ReportId == reportId)
                .OrderBy(t => t.Id, OrderByType.Desc)
                .ToList().FirstOrDefault();
        }

        public List<OrtVoltageModel> GetVolts(long headId)
        {
            return dbContext.QcDb.Queryable<OrtVoltageModel>()
                .Where(d => d.HeadId == headId)
                .ToList();
        }
        public List<OrtDtlModel> GetDtls(long headId)
        {
            List <OrtDtlModel> dtls =  dbContext.QcDb.Queryable<OrtDtlModel>().Where(d => d.HeadId == headId)
                .OrderBy(d => d.SNo, OrderByType.Asc)
                .ToList();
            if (dtls != null)
            {
                foreach(OrtDtlModel d in dtls)
                {
                    d.ElectricViewModels = new List<ElectricViewModel>();
                    d.SizeViewModels = new List<SizeViewModel>();
                }
            }
            return dtls;
        }

        public OrtDtlModel GetDtl(long headId,int sno)
        {
            OrtDtlModel dtls = dbContext.QcDb.Queryable<OrtDtlModel>()
                .Where(d => d.HeadId == headId && d.SNo== sno)
                .OrderBy(d => d.SNo, OrderByType.Asc)
                .First();
            if (dtls != null)
            {
                    dtls.ElectricViewModels = new List<ElectricViewModel>();
                    dtls.SizeViewModels = new List<SizeViewModel>();
            }
            return dtls;
        }

        public List<string> GetDtlUsers()
        {
            List<string> list = new List<string>();
            var r = dbContext.QcDb.Queryable<OrtDtlModel>()
             .GroupBy(it => new { it.CreateUser}).Select(it => new { it.CreateUser }).ToList();

            if(r.Any())
            {
                r.ForEach(t => list.Add(t.CreateUser));
            }

            return list;
        }
         
        public List<OrtDtlView> GetDtlView(string username,DateTime startDate, DateTime endDate)
        {
            return dbContext.QcDb.Queryable<OrtHeadModel, OrtDtlModel>((head, dtl) => new object[] {
                 JoinType.Inner,head.Id==dtl.HeadId})
                .WhereIF(OrtFilter.NoBad, head => head.Level == "A")
                .WhereIF(!string.IsNullOrEmpty(username),(head, dtl) => dtl.CreateUser == username)
                .Where((head, dtl) => dtl.CreateDate >= startDate.Date 
                    && dtl.CreateDate < endDate.AddDays(1).Date
                    )
                .Select((head, dtl) => 
                    new OrtDtlView {
                        BillNo = head.BillNo,
                        LotNo = head.LotNo,
                        SNo = dtl.SNo,
                        SourceNo = head.SourceNo,
                        Customer = head.Customer,
                        Cap = head.Cap,
                        Voltage = head.Voltage,
                        CreateDate = dtl.CreateDate,
                        Series = head.Series,
                        Size = head.Size,
                        Pn = head.Pn,
                        CreateUser = dtl.CreateUser,
                        Remark = dtl.Remark,
                        Temp = dtl.Temp,
                        TestTime = dtl.TestTime,
                        Condiction = dtl.Condiction,
                        ExpireDate = dtl.ExpireDate
                    })
                .ToList();
        }

        public List<OrtDataModel> GetDatas(long headId, int sNo)
        {
            return dbContext.QcDb.Queryable<OrtDataModel>()
                .Where(d => d.HeadId == headId && d.SNo == sNo)
                .ToList();
        }

        public List<OrtDataModel> GetDatas(string billNo, int sNo)
        {
            return dbContext.QcDb.Queryable<OrtDataModel,OrtHeadModel>(
                (d,h)=>new JoinQueryInfos(JoinType.Inner,d.HeadId == h.Id)
                )
                .Where((d,h) => h.BillNo == billNo && d.SNo == sNo)
                .Select<OrtDataModel>()
                .ToList();
        }
        public List<OrtDataModel> GetDatas(long headId)
        {
            return dbContext.QcDb.Queryable<OrtDataModel>()
                .Where(d => d.HeadId == headId)
                .ToList();
        }

        public List<OrtDataModel> GetDatas(OrtHeadModel headModel, OrtDtlModel dtl)
        {
            if (headModel == null || dtl == null || headModel.Id <= 0 || dtl.SNo <= 0) return null;
            //dtl.CreateSNo(headModel.ElectricQty, headModel.SizeQty, dtl.SNo);
            List<OrtDataModel> datas = GetDatas(headModel.Id, dtl.SNo);
            ViewModelTrans<OrtDataModel>.DataToView(dtl.SNo, datas, dtl.ElectricViewModels, dtl.SizeViewModels);
            return datas;
        }

        public OrtHeadModel GetHeadByBillNo(string billNo)
        {
            var heads = dbContext.QcDb.Queryable<OrtHeadModel>().Where(o => o.BillNo == billNo);
            if (heads != null && heads.Count() > 0)
                return heads.First();
            else
                return null;
        }

        public OrtHeadModel GetHeadById(long id)
        {
            var heads = dbContext.QcDb.Queryable<OrtHeadModel>().Where(o => o.Id == id);
            if (heads != null && heads.Count() > 0)
                return heads.First();
            else
                return null;
        }

        public List<OrtHeadModel> GetHeads(int count,string billType)
        {
            return dbContext.QcDb.Queryable<OrtHeadModel>()
                .Where(o => o.BillType == billType)
                .WhereIF(OrtFilter.NoBad, o=>o.Level =="A")
                .OrderBy(o => o.TestDate, OrderByType.Desc)
                .Take(count).ToList();
        }

        public int Save(OrtHeadModel ortHeadModel)
        {
            int i = 0;
            List<OrtDataModel> datas = new List<OrtDataModel>();
            if(ortHeadModel.Dtls.Count>0)
            {
                foreach(OrtDtlModel dtl in ortHeadModel.Dtls)
                {
                    dtl.HeadId = ortHeadModel.Id;
                    List<OrtDataModel> dtl_datas = new List<OrtDataModel>();
                    if (dtl.ElectricViewModels!= null && dtl.ElectricViewModels.Count>0)
                    {
                        dtl_datas.AddRange(ViewModelTrans<OrtDataModel>.ElectricViewToData(ortHeadModel.Id, dtl.SNo, dtl.ElectricViewModels));
                    }
                    if (dtl.SizeViewModels != null && dtl.SizeViewModels.Count > 0)
                    {
                        dtl_datas.AddRange(ViewModelTrans<OrtDataModel>.SizeViewToData(ortHeadModel.Id, dtl.SNo, dtl.SizeViewModels));
                    }

                    dtl.Datas = dtl_datas;
                    datas.AddRange(dtl_datas);
                }

                var overLengths = datas.Where(d => d.Value > 9999999999);
                if (overLengths != null && overLengths.Count() > 0)
                    overLengths.ToList().ForEach(o => o.Value = 9999999999);
                var overLengths2 = datas.Where(d => d.Value < -9999999999);
                if (overLengths2 != null && overLengths2.Count() > 0)
                    overLengths2.ToList().ForEach(o => o.Value = -9999999999);
            }

            try
            {
                bool isNEW = false;
                dbContext.QcDb.Ado.BeginTran();

                if(ortHeadModel.Id <=0)
                {
                    dbContext.QcDb.Insertable(ortHeadModel)
                    .ExecuteCommandIdentityIntoEntity();

                    if(ortHeadModel.Dtls != null && ortHeadModel.Dtls.Count>0)
                    {
                        ortHeadModel.Dtls.ForEach(t => t.HeadId = ortHeadModel.Id);
                    }
                    if (datas.Count > 0)
                        datas.ForEach(t => t.HeadId = ortHeadModel.Id);
                    i = 1;
                }
                else
                {
                    i = dbContext.QcDb.Updateable(ortHeadModel)
                    .ExecuteCommand();
                }
                dbContext.QcDb.Deleteable<OrtDataModel>()
                    .Where(o => o.HeadId == ortHeadModel.Id)
                    .ExecuteCommand();

                List<OrtDtlModel> dtls = ortHeadModel.Dtls.Where(d => d.Id > 0).ToList();
                if(dtls != null && dtls.Count >0)
                dbContext.QcDb.Updateable(dtls)
                    .ExecuteCommand();
                dtls = ortHeadModel.Dtls.Where(d => d.Id <= 0).ToList();
                if (dtls != null && dtls.Count > 0)
                {
                    foreach(var dtl in dtls)
                    {
                        dbContext.QcDb.Insertable(dtl)
                        .ExecuteCommandIdentityIntoEntity();
                    }
                    //dbContext.QcDb.Insertable(dtls)
                    //.ExecuteCommand();
                }
                if(datas.Count > 0)
                    dbContext.QcDb.Insertable(datas)
                    .ExecuteCommand();

                List<OrtVoltageModel> volts = ortHeadModel.Volts.Where(d => d.Id > 0).ToList();
                if (volts != null && volts.Count > 0)
                    dbContext.QcDb.Updateable(volts)
                        .ExecuteCommand();
                volts = ortHeadModel.Volts.Where(d => d.Id <= 0).ToList();
                if (volts != null && volts.Count > 0)
                {
                    volts.ForEach(t => t.HeadId = ortHeadModel.Id);
                    dbContext.QcDb.Insertable(volts)
                    .ExecuteCommand();
                }

                dbContext.QcDb.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                if (ex.Message.Contains("idx_t_ort_head_billno"))
                {
                    ortHeadModel.BillNo = GetBillNo(ortHeadModel, false);
                     i= Save(ortHeadModel);
                }
                else
                {
                    Logger.LogError(ex);
                    throw ex;
                }
            }
            return i;
        }

        public string GetBillNo(OrtHeadModel ortHeadModel, bool isAdd)
        {
            string billNo = string.Empty;

            //单据字母前缀 + yyMMdd + 3位流水号
            string prefix = string.Empty;
            if (string.IsNullOrWhiteSpace(ortHeadModel.BillNo) || ortHeadModel.BillNo.StartsWith(ortHeadModel.BillType))
                prefix = ortHeadModel.BillType + ortHeadModel.TestDate.ToString("yyMMdd");
            else
            {
                Regex re = new Regex(@"[a-zA-Z]+");
                Match m = re.Match(ortHeadModel.BillNo);
                prefix = m.Value + ortHeadModel.TestDate.ToString("yyMMdd");
            }
            int billNoLength = prefix.Length + 3;
            //string sql = "select max(BillNo) from t_ort_head where BillType = @BillType and BillNo like @Prefix and len(BillNo)=" 
            //    + billNoLength.ToString();
            var billNo2 = dbContext.QcDb.Queryable<OrtHeadModel>()
                .Where(t => t.BillType == ortHeadModel.BillType && t.BillNo.StartsWith(prefix) && t.BillNo.Length == billNoLength)
                .Max(t => t.BillNo);
            //var dt = dbContext.QcDb.Ado.GetDataTable(sql, new SugarParameter[]{
            //  new SugarParameter("@BillType",ortHeadModel.BillType),
            //  new SugarParameter("@Prefix",prefix+ "%")
            //});

            int no = 1;
            if (!string.IsNullOrWhiteSpace(billNo2))
            {
                int.TryParse(billNo2.Replace(prefix, string.Empty), out no);
                billNo = prefix + (no + 1).ToString().PadLeft(3, '0');
            }
            else
                billNo = prefix + (no).ToString().PadLeft(3, '0');
            //if (dt!= null && dt.Rows.Count>0)
            //{
            //    int.TryParse(dt.Rows[0][0].ToString().Replace(prefix, string.Empty), out no);
            //    billNo = prefix + (no + 1).ToString().PadLeft(3, '0');
            //}

            ortHeadModel.BillNo = billNo;
            if (isAdd)
            {
                try
                {
                    dbContext.QcDb.Insertable(ortHeadModel).ExecuteCommandIdentityIntoEntity();
                }
                catch (Exception ex)
                {
                    ortHeadModel.BillNo = ortHeadModel.BillType + ortHeadModel.TestDate.ToString("yyyyMMddHHmmss");
                    dbContext.QcDb.Insertable(ortHeadModel).ExecuteCommandIdentityIntoEntity();
                }
            }
            else
            {
                try
                {
                    dbContext.QcDb.Updateable(ortHeadModel).ExecuteCommand();
                }
                catch (Exception ex)
                {
                    ortHeadModel.BillNo = ortHeadModel.BillType + ortHeadModel.TestDate.ToString("yyyyMMddHHmmss");
                    dbContext.QcDb.Updateable(ortHeadModel).ExecuteCommand();
                }
            }

            return ortHeadModel.BillNo;
        }

        /// <summary>
        /// 複製，不包含檢測數據
        /// </summary>
        /// <param name="ortHeadModel"></param>
        /// <returns></returns>
        public OrtHeadModel Clone(OrtHeadModel ortHeadModel)
        {
            OrtHeadModel newModel;
            if (ortHeadModel == null)
                newModel = new OrtHeadModel();
            else newModel = ClassClone<OrtHeadModel, OrtHeadModel>.Clone(ortHeadModel);
            newModel.Id = 0;
            newModel.ModiDate = null;
            newModel.ModiUser = string.Empty;
            newModel.FinishDate = DateTime.Parse("2099-12-31");
            if (newModel.Dtls != null && newModel.Dtls.Count > 0)
            {
                newModel.Dtls = new List<OrtDtlModel>();
                //OrtDtlModel dtl = newModel.OrtDtls[0];
                //dtl.Temp = "℃/%RH()";
                //dtl.TestTime = 0;
                //dtl.HeadId = 0;
                //dtl.SNo = 1;
                //newModel.OrtDtls.Clear();
                //newModel.OrtDtls.Add(dtl);
                //if (dtl.Datas != null && dtl.Datas.Count > 0)
                //    dtl.Datas.Clear();
                //if (dtl.ElectricViewModels != null && dtl.ElectricViewModels.Count > 0)
                //{
                //    dtl.ElectricViewModels.Clear();
                //}
                //if(newModel.ElectricQty>0)
                //{
                //    for(int i=0;i< newModel.ElectricQty;i++)
                //    {
                //        dtl.ElectricViewModels.Add(new ElectricViewModel());
                //    }
                //}
                //if (dtl.SizeViewModels != null && dtl.SizeViewModels.Count > 0)
                //{
                //    dtl.SizeViewModels.Clear();
                //}
                //if (newModel.SizeQty > 0)
                //{
                //    for (int i = 0; i < newModel.SizeQty; i++)
                //    {
                //        dtl.SizeViewModels.Add(new SizeViewModel());
                //    }
                //}
            }

            return newModel;
        }

        /// <summary>
        /// 審核
        /// </summary>
        /// <param name="ortList"></param>
        /// <returns></returns>
        public int Approve(List<OrtHeadModel> ortList)
        {
            int i = 0;
            i = dbContext.QcDb.Updateable(ortList)
                .UpdateColumns(it => new { it.ApproveUser, it.ApproveDate })
                .ExecuteCommand();
            if (i > 0) UpdateFinishDate(ortList);
            return i;
        }


        /// <summary>
        /// 反審核
        /// </summary>
        /// <param name="ortList"></param>
        /// <returns></returns>
        public int UnApprove(List<OrtHeadModel> ortList)
        {
            int i = 0;
            if (ortList != null && ortList.Count > 0)
            {
                string date = "2099-12-30";
                ortList.ForEach(o => o.FinishDate = DateTime.Parse(date));
                i = dbContext.QcDb.Updateable(ortList)
                    .UpdateColumns(it => new { it.ApproveUser, it.ApproveDate, it.FinishDate })
                    .ExecuteCommand();
            }
            return i;
        }

        /// <summary>
        /// 审核和反审核更新完成日期
        /// </summary>
        /// <param name="IsApprove">true 审核   false 反审核</param>
        /// <param name="ortList"></param>
        public void UpdateFinishDate(List<OrtHeadModel> ortList)
        {
            if (ortList == null && ortList.Count == 0) return;
            string sql = string.Format(@"  update a 
  set[FinishDate] = isnull(b.TestDate, GetDate())
  from[dbo].[t_ort_head] a
  left join(
      select z.HeadId, TestDate = Max(TestDate)

      from[dbo].[t_ort_dtl] z

      group by z.HeadId
  ) b
  on a.Id = b.HeadId
  where a.Id in ({0})", string.Join(",", ortList.Select(t => t.Id)));

            dbContext.QcDb.Ado.ExecuteCommand(sql);
        }

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="ortList"></param>
        /// <returns></returns>
        public int Delete(List<OrtHeadModel> ortList)
        {
            int i = 0;
            try
            {
                dbContext.QcDb.Ado.BeginTran();

                dbContext.QcDb.Deleteable<OrtDataModel>()
                    .In(it => it.HeadId, ortList.Select(o => o.Id).ToArray())
                    .ExecuteCommand();
                dbContext.QcDb.Deleteable<OrtDtlModel>()
                    .In(it => it.HeadId, ortList.Select(o => o.Id).ToArray())
                    .ExecuteCommand();
                i = dbContext.QcDb.Deleteable(ortList)
                    .ExecuteCommand();
                dbContext.QcDb.Ado.CommitTran();
            }
            catch(Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }
            return i;
        }

        /// <summary>
        /// 刪除測試次數
        /// </summary>
        /// <param name="ortList"></param>
        /// <returns></returns>
        public int DeleteDtl(OrtDtlModel dtl)
        {
            int i = 0;
            try
            {
                dbContext.QcDb.Ado.BeginTran();
                dbContext.QcDb.Deleteable<OrtDataModel>()
                    .Where(it => it.HeadId==dtl.HeadId && it.SNo == dtl.SNo)
                    .ExecuteCommand();
                i = dbContext.QcDb.Deleteable<OrtDtlModel>()
                    .Where(it => it.HeadId == dtl.HeadId && it.SNo == dtl.SNo)
                    .ExecuteCommand();
                dbContext.QcDb.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }

            return i;
        }

        public int DeleteDtlDatas(int headId, int sno)
        {
            int i = 0;
            try
            {
                dbContext.QcDb.Deleteable<OrtDataModel>()
                    .Where(it => it.HeadId == headId && it.SNo == sno)
                    .ExecuteCommand();
            }
            catch (Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }

            return i;
        }


        public List<OrtHeadModel> Query(OrtFilter filter)
        {
            if (filter == null) return GetHeads(100);
            bool isLeve = (filter.IsA || filter.IsB || filter.IsC);
            List<string> levelList = new List<string>();
            if(isLeve)
            {
                if (filter.IsA) levelList.Add("A");
                if(filter.IsB) levelList.Add("B");
                if (filter.IsC) levelList.Add("C");
            }

            List<string> billNos = new List<string>();
            if(!string.IsNullOrWhiteSpace(filter.BillNo) &&  filter.BillNo.Contains(","))
            {
                billNos.AddRange(filter.BillNo.Split(','));
            }

            List<string> lotNos = new List<string>();
            if (!string.IsNullOrWhiteSpace(filter.LotNo) && filter.LotNo.Contains(","))
            {
                lotNos.AddRange(filter.LotNo.Split(','));
            }

            return dbContext.QcDb.Queryable<OrtHeadModel>()
                .WhereIF(!filter.AllBill, t => t.BillType == filter.BillType)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Pn), t => t.Pn == filter.Pn)
                .WhereIF(OrtFilter.NoBad, o => o.Level == "A")
                .WhereIF(filter.IsBillNo && !string.IsNullOrWhiteSpace(filter.StartBillNo)
                    , t => SqlFunc.Between(t.BillNo, filter.StartBillNo, filter.EndBillNo))
                .WhereIF(!string.IsNullOrWhiteSpace(filter.BillNo) && billNos.Count == 0, t => t.BillNo == filter.BillNo)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.BillNo) && billNos.Count > 0, t => billNos.Contains(t.BillNo))
                .WhereIF(!string.IsNullOrWhiteSpace(filter.LotNo) && lotNos.Count == 0, t => t.LotNo.StartsWith(filter.LotNo))
                .WhereIF(!string.IsNullOrWhiteSpace(filter.LotNo) && lotNos.Count > 0, t => lotNos.Contains(t.LotNo))
                //.WhereIF(!string.IsNullOrWhiteSpace(filter.LotNo), t => t.LotNo == filter.LotNo)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Customer), t => t.Customer == filter.Customer)
                .WhereIF(filter.IsModiDate, t => t.ModiDate >= filter.StartModiDate.Date)
                .WhereIF(filter.IsModiDate, t => t.ModiDate < filter.EndModiDate.AddDays(1).Date)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Series), t => t.Series == filter.Series)
                .WhereIF(filter.Cap >0, t => t.Cap == filter.Cap)
                .WhereIF(filter.Voltage > 0, t => t.Voltage == filter.Voltage)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Size), t => t.Size == filter.Size)
                .WhereIF(filter.IsFinished && !filter.IsUnFinished, t => !SqlFunc.IsNullOrEmpty(t.ApproveUser))
                .WhereIF(!filter.IsFinished && filter.IsUnFinished, t => SqlFunc.IsNullOrEmpty(t.ApproveUser))
                .WhereIF(isLeve, t => levelList.Contains(t.Level))
                .WhereIF(isLeve, t => t.IsValid)
                .WhereIF(filter.IsTestDate, t => t.TestDate >= filter.StartTestDate.Date)
                .WhereIF(filter.IsTestDate, t => t.TestDate < filter.EndTestDate.AddDays(1).Date)
                .WhereIF(filter.IsFinishDate, t => t.FinishDate >= filter.StartFinishDate.Date)
                .WhereIF(filter.IsFinishDate, t => t.FinishDate < filter.EndFinishDate.AddDays(1).Date)
                .WhereIF(filter.IsExpireDate, t => t.ExpireDate >= filter.StartExpireDate.Date)
                .WhereIF(filter.IsExpireDate, t => t.ExpireDate < filter.EndExpireDate.AddDays(1).Date)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Paste), t => SqlFunc.Equals(t.Paste, filter.Paste))
                .WhereIF(filter.TestTemp>0, t => SqlFunc.Equals(t.TestTemp, filter.TestTemp))
                .WhereIF(!string.IsNullOrWhiteSpace(filter.BoxNo), t => SqlFunc.Equals(t.BoxNo, filter.BoxNo))
                .WhereIF(filter.ReportId > 0, t => t.ReportId == filter.ReportId)
                .WhereIF(filter.IsValidIndex == 1, t => t.IsValid == true)
                .WhereIF(filter.IsValidIndex == 2, t => t.IsValid == false)
                .OrderBy(t => t.TestDate, OrderByType.Desc)
                .Take(filter.RowCount).ToList();

        }

        public string GenStandard(OrtHeadModel head,OrtDtlModel dtl,string reportCode)
        {
            string data = "";
            if (head == null || dtl == null) return "";
            int rowIndex = head.Dtls.IndexOf(dtl);
            try
            {
                head.Standard.DMax = head.DMax;
                head.Standard.LMax = head.LMax;
                head.Standard.CMax = head.FMax;

                double capMaxRate, capMinRate;
                capMaxRate = 20;
                capMinRate = -20;
                //if (string.IsNullOrWhiteSpace(head.Pn))
                //{
                //    ProductCode.GetCapRange(head.Pn, out capMinRate, out capMaxRate);
                //}
                capMaxRate = head.CapMax;
                capMinRate = head.CapMin;

                int capNum = ProductCode.GetCapStandardNum(head.Cap);
                if (dtl == null || dtl.SNo == 1)
                {
                    if (capMaxRate == 0 && capMinRate == 0)
                    {
                        capMaxRate = 20;
                        capMinRate = -20;
                    }
                    if (head.Cap > 0)
                    {
                        head.Standard.CapMax = Math.Round(head.Cap * (1 + capMaxRate / 100), capNum);
                        head.Standard.CapMin = Math.Round(head.Cap * (1 + capMinRate / 100), capNum);
                    }

                    head.Standard.ZMax = head.ZMax;
                    head.Standard.EsrMax = head.EsrMax;
                    head.Standard.DfMax = head.DfMax;
                    if (head.Standard.EsrMax == 0 && head.EsrMaxAfter > 0) head.Standard.EsrMax = head.EsrMaxAfter;
                }
                else
                {
                    if (head.Cap > 0)
                    {
                        if (head.CapRate == 0)
                        {
                            head.Standard.CapMax = Math.Round(head.Cap * (1 + capMaxRate / 100), capNum);
                            head.Standard.CapMin = Math.Round(head.Cap * (1 + capMinRate / 100), capNum);
                        }
                        else
                        {
                            head.Standard.CapMax = Math.Round(head.Cap * (1 + head.CapRate / 100), capNum);
                            head.Standard.CapMin = Math.Round(head.Cap * (1 - head.CapRate / 100), capNum);
                        }
                    }

                    if (head.ZRate > 1)
                        head.Standard.ZMax = head.ZMax * head.ZRate;
                    else
                        head.Standard.ZMax = head.ZMax;

                    if (head.DfMaxAfter > 0) head.Standard.DfMax = head.DfMaxAfter;
                    else if (head.DfMax > 0) head.Standard.DfMax = head.DfMax;

                    if (head.EsrMaxAfter > 0) head.Standard.EsrMax = head.EsrMaxAfter;
                    else if (head.EsrMax > 0) head.Standard.EsrMax = head.EsrMax;
                }

                head.Standard.LcMax = head.LcMax;
                if(dtl.SNo > 1)
                head.Standard.LcMax = head.LcMaxAfter;
                if(head.Standard.LcMax ==0) head.Standard.LcMax = head.LcMax;

                if ((reportCode == "JIS004" || reportCode == "R009") && dtl.SNo > 1)
                {
                    if(head.LcMax>0)
                    {
                        double temp = 0;
                        if (!string.IsNullOrWhiteSpace(dtl.Condiction))
                        {
                            string temps = dtl.Condiction.Replace("℃", string.Empty).Replace(" ", string.Empty);
                            double.TryParse(temps, out temp);
                        }
                        double times = StandardView.GetTempLcTimes(temp);
                        head.Standard.LcMax = head.LcMax * times;
                    }

                    if(head.ZRate >1 && head.ZMax>0)
                    {
                        head.Standard.ZMax = head.ZMax * head.ZRate;
                    }
                }
                //R001
                //R002
                if (head.DfMaxAfter == 0 && head.DfMax > 0)
                {
                    if (reportCode == "R001" || reportCode == "R002")
                    {
                        head.DfMaxAfter = 2 * head.DfMax;
                    }
                    else if(reportCode == "R005")
                        head.DfMaxAfter = 1.2 * head.DfMax;
                    else
                        head.DfMaxAfter = head.DfMax;
                }

                if (head.BillType == "FQC")
                    GetFqcStd(head);
            }
            catch(Exception ex)
            {
                Logger.LogError(ex);
                throw ex;
            }

            return data;
        }

        public void GetFqcStd(OrtHeadModel head)
        {
            BackgroundWorker worker = new BackgroundWorker();
            string data = "";
            worker.DoWork += (s, a) =>
            {
                try
                {
                    #region mark
                    string apiurl = SysParamService.GetSysParamValue(dbContext, "ErpApiUrl");
                    if (string.IsNullOrEmpty(apiurl)) apiurl = "http://192.168.32.99";
                    string url = apiurl + "/api/FQC_standard?workno=" + head.SourceNo;
                    try
                    {
                        data = ApiHelper.HttpPost2(url, string.Empty, "POST");
                    }
                    catch(Exception ex)
                    {
                        OrtService.FqcApiData = ex.Message; 
                    }
#if DEBUG
                    if (string.IsNullOrWhiteSpace(data))
                        data = "[{\"ItemName\":\"item_No\",\"Standard\":\"TL-1J212M6N1845BCE\"},{\"ItemName\":\"capMax\",\"Standard\":\"2520.0\"},{\"ItemName\":\"capMin\",\"Standard\":\"1701.00\"},{\"ItemName\":\"fqc_df\",\"Standard\":\"9.5\"},{\"ItemName\":\"fqc_lc\",\"Standard\":\"793.800\"},{\"ItemName\":\"fqc_impd\",\"Standard\":\"0.06\"},{\"ItemName\":\"fqc_esr\",\"Standard\":\"0.4\"},{\"ItemName\":\"fqc_heightMin\",\"Standard\":\"45\"},{\"ItemName\":\"fqc_heightMax\",\"Standard\":\"46.5\"},{\"ItemName\":\"fqc_diaMin\",\"Standard\":\"18\"},{\"ItemName\":\"fqc_diaMax\",\"Standard\":\"18.5\"},{\"ItemName\":\"fqc_No01\",\"Standard\":\"01050V105M036\"},{\"ItemName\":\"fqc_No02\",\"Standard\":\"10040P036\"},{\"ItemName\":\"fqc_No03\",\"Standard\":\"220236301L\"},{\"ItemName\":\"fqc_No04\",\"Standard\":\"220236250L\"},{\"ItemName\":\"fqc_No05\",\"Standard\":\"3NMR5D150039\"},{\"ItemName\":\"fqc_No06\",\"Standard\":\"\"},{\"ItemName\":\"fqc_No07\",\"Standard\":\"418050R0\"},{\"ItemName\":\"fqc_No08\",\"Standard\":\"5R18465E\"},{\"ItemName\":\"fqc_No09\",\"Standard\":\"6918PF\"},{\"ItemName\":\"fqc_No10\",\"Standard\":\"7KHP200A\"}]";
#endif

                    #endregion mark
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex);
                    throw ex;
                }
            };
            worker.RunWorkerCompleted += (s, a) =>
            {
                if (!string.IsNullOrWhiteSpace(data))
                {
                    OrtService.FqcApiData = data;
                    Logger.LogMessage(data);
                    var data2 = data.Replace("\\\"", "\"").TrimStart('"').TrimEnd('"')
                        .Replace("NULL", "null");
                    var stds = data2.ToObject<List<ErpStdView>>();

                    if (stds != null && stds.Count > 0)
                    {
                        #region 标准
                        if (head.BillType == "FQC")
                        {
                            double st = 0d;
                            var std = stds.Where(t => t.ItemName.ToUpper() == "CAPMAX").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                    head.Standard.CapMax = st;
                            }
                            std = stds.Where(t => t.ItemName.ToUpper() == "CAPMIN").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                    head.Standard.CapMax = st;
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_df").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.DfMax = st;
                                    head.DfMax = st;
                                    head.DfMaxAfter = st;
                                }
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_lc").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.LcMax = st;
                                    head.LcMax = st;
                                    head.LcMaxAfter = st;
                                }
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_impd").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.ZMax = st * 1000d;
                                    head.ZMax = st * 1000d;
                                }
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_esr").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.EsrMax = st * 1000d;
                                    head.EsrMax = st * 1000d;
                                    head.EsrMaxAfter = st * 1000d;
                                }
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_heightmin").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.LMin = st;
                                }
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_heightmax").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.LMax = st;
                                    head.LMax = st;
                                }
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_diamin").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.DMin = st;
                                }
                            }
                            std = stds.Where(t => t.ItemName.ToLower() == "fqc_diamax").FirstOrDefault();
                            if (std != null)
                            {
                                if (double.TryParse(std.Standard, out st))
                                {
                                    head.Standard.DMax = st;
                                    head.DMax = st;
                                }
                            }
                        }
                        #endregion 标准
                    }
                }
            };

            worker.RunWorkerAsync();
        }

        public bool TranDataToOtherDtl(OrtHeadModel sourceHead, OrtDtlModel sourceDtl
            , OrtHeadModel targetHead, int targetSNo,out string msg)
        {
            msg = string.Empty;
            if (sourceHead == null || sourceDtl == null || targetHead == null || targetSNo <= 0
                || sourceDtl.ElectricViewModels.Count<=0)
                return false;

            bool flag = false;
            OrtDtlModel targetDtl = null;
            List<OrtDtlModel> targetDtls = GetDtls(targetHead.Id);
            if(targetDtls != null && targetDtls.Count>0)
            {
                var dd = targetDtls.Where(t => t.SNo == targetSNo);
                if(dd.Any())
                {
                    targetDtl = dd.First();
                }
            }

            bool isNewDtl = false;
            if (targetDtl == null)
            {
                isNewDtl = true;
                targetDtl = new OrtDtlModel(targetHead.ElectricQty, targetHead.SizeQty, targetSNo, targetHead.Id);
                targetDtl.ElectricViewModels.Clear();
                targetDtl.SizeViewModels.Clear();
            }

            int count = sourceDtl.ElectricViewModels.Count - 1;
            for (int i= count; i>= targetHead.ElectricQty; i--)
            {
                targetDtl.ElectricViewModels.Add(sourceDtl.ElectricViewModels[i]);
                sourceDtl.ElectricViewModels.RemoveAt(i);
            }

            targetDtl.ElectricViewModels.Reverse();
            GenStandard(targetHead, targetDtl, string.Empty);
            //目标数据重新判断是否合格
            foreach(ElectricViewModel m in targetDtl.ElectricViewModels)
            {
                if (m.CAP > 0)
                    m.CAPisValid = targetHead.Standard.IsValid(ItemCode.CAP, m.CAP);
                if (m.DF > 0)
                    m.DFisValid = targetHead.Standard.IsValid(ItemCode.DF, m.DF);
                if (m.LC > 0)
                    m.LCisValid = targetHead.Standard.IsValid(ItemCode.LC, m.LC);
                if (m.ESR > 0)
                    m.ESRisValid = targetHead.Standard.IsValid(ItemCode.ESR, m.ESR);
                if (m.Z > 0)
                    m.ZisValid = targetHead.Standard.IsValid(ItemCode.Z, m.Z);

                if (m.LC2 > 0)
                    m.LC2isValid = targetHead.Standard.IsValid(ItemCode.LC2, m.LC2);
                if (m.ESR2 > 0)
                    m.ESR2isValid = targetHead.Standard.IsValid(ItemCode.ESR2, m.ESR2);
                if (m.Z2 > 0)
                    m.Z2isValid = targetHead.Standard.IsValid(ItemCode.Z2, m.Z2);
            }

            List<OrtDataModel> sourceDatas = new List<OrtDataModel>();
            List<OrtDataModel> targetDatas = new List<OrtDataModel>();
            if (sourceDtl.ElectricViewModels != null && sourceDtl.ElectricViewModels.Count > 0)
            {
                sourceDatas.AddRange(ViewModelTrans<OrtDataModel>.ElectricViewToData(sourceHead.Id, sourceDtl.SNo
                    , sourceDtl.ElectricViewModels));
            }
            if (targetDtl.ElectricViewModels != null && targetDtl.ElectricViewModels.Count > 0)
            {
                targetDatas.AddRange(ViewModelTrans<OrtDataModel>.ElectricViewToData(targetHead.Id, targetSNo
                    , targetDtl.ElectricViewModels));
            }

            targetDtl.Datas = targetDatas;
            sourceDtl.Datas = sourceDatas;

            dbContext.QcDb.Ado.BeginTran();
            if (isNewDtl)
            {
                dbContext.QcDb.Insertable(targetDtl).ExecuteCommand();
            }
            //else
            //{
            //    dbContext.QcDb.Insertable(targetDtl.Datas).ExecuteCommand();
            //}
            dbContext.QcDb.Insertable(targetDtl.Datas).ExecuteCommand();
            dbContext.QcDb.Deleteable<OrtDataModel>()
                .Where(it => it.HeadId == sourceHead.Id && it.SNo == sourceDtl.SNo)
                .ExecuteCommand();
            dbContext.QcDb.Insertable(sourceDtl.Datas).ExecuteCommand();
            dbContext.QcDb.Ado.CommitTran();

            return true;
        }

        public bool SaveDoubleTest(List<ElectricViewModel> list)
        {
            bool flag = false;
            if (list == null || list.Count == 0) return false;

            var headIds = list.Select(t => t.HeadId).Distinct().ToList();
            if (headIds == null || headIds.Count == 0) return flag;
            var db = new AllDbContext();

            try
            {
                db.QcDb.Ado.BeginTran();
                for (int i = 0; i < headIds.Count; i++)
                {
                    if (headIds[i] <= 0) continue;
                    var snos = list.Where(t=>t.HeadId== headIds[i]).Select(t => t.SNo).Distinct().ToList();
                    for(int j=0;j<snos.Count;j++)
                    {
                        var dataViews = list.Where(t => t.HeadId == headIds[i] && t.SNo == snos[j]).ToList();
                        if (dataViews == null || dataViews.Count == 0) continue;
                        List<OrtDataModel> datas = new List<OrtDataModel>();
                        datas.AddRange(ViewModelTrans<OrtDataModel>.ElectricViewToData(headIds[i], snos[j], dataViews));
                        //dbContext.QcDb.Deleteable<OrtDataModel>()
                        //    .Where(o => o.HeadId == headIds[i] && o.SNo == snos[j]).ExecuteCommand();

                        var datas2 = datas.Where(t => t.Value > 0).ToList();
                        if (datas2.Any())
                        {
                            db.QcDb.Insertable(datas).ExecuteCommand();
                            datas.Clear(); 
                        }
                        datas = null;
                    }
                }

                db.QcDb.Ado.CommitTran();
                flag = true;
            }
            catch (Exception ex)
            {
                db.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }

            return flag;
        }
    }
}
